#!/bin/sh

# ===========================================================================
# 功能: 项目启动脚本
# 作者: x
# 时间: 2024-06-20
# 注意: 脚本建议以root权限执行,
# 使用方式: 将此脚本放置在jar同级目录下 ./x.sh start 启动 stop 停止 restart 重启 status 状态 log 日志 back 备份
# ===========================================================================

# jar包名称  一般情况下只需要改这个地方  注意: 不可与服务器上的jar重名
AppName=szdh-server.jar
# 指定启动端口
SERVER_PORT=48080
# Java环境变量
JAVA_HOME=""
# 指定日志地址
LOG_FILE=./logs/$AppName.log
# JVM参数
JVM_OPTS="-Dname=$AppName  -Duser.timezone=Asia/Shanghai -Xms128m -Xmx1024m"
# 获取项目路径
APP_HOME=$(dirname "$(readlink -f "$0")")
# 时间
TIME=`date +'%Y%m%d%H%M%S'`


echo "项目路径:$APP_HOME"

# 日志函数
function log() {
    # 先判断日志目录
    if [ ! -d "$APP_HOME/logs" ]; then
        mkdir "$APP_HOME/logs" || { echo "目录 创建 错误"; return 1; }
    fi
    # 如果日志文件不存在，则创建日志文件
    if [ ! -f "$LOG_FILE" ]; then
        touch "$LOG_FILE" || { echo "文件 创建 错误"; return 1; }
    fi
    # 实时查看日志文件内容
    tail -f  "$LOG_FILE"
}

# 获取进程ID函数
function pid() {
    # 检查jar包是否存在
    if [ ! -f "$APP_HOME/$AppName" ]; then
        echo "未找到 $AppName"
        exit 1
    fi
    # 使用ps命令查找与AppName相关的Java进程，并提取进程ID
    local PID=$(ps -ef | grep "[j]ava" | grep -w "$AppName" | grep -v grep | awk '{print $2}')
    if [ -n "$PID" ]; then
        echo "$PID"
    else
        echo "0"
    fi
}

# 获取端口函数
function port() {
    local pid="$1"
    # 使用lsof命令查找指定进程监听的端口
    local output=$(lsof -nP -a -p "$pid" -i tcp 2>/dev/null)

    if [ -n "$output" ]; then
        # 提取端口号
        local PORT=$(echo "$output" | awk '/LISTEN/{split($9, a, ":"); print a[2]}')
        if [ -n "$PORT" ]; then
            echo "$PORT"
        else
            echo "未找到监听的端口"
            echo "0"
        fi
    else
        echo "无相关进程运行或未监听端口"
        echo "0"
    fi
}

# 启动函数
function start() {
    PID=$(pid)
    PORT=$(port $PID)
    if [ "$PID" != 0 ]; then
         status
    else
        # 如果进程未运行，则启动项目
        if [ "$SERVER_PORT" != 0 ]; then
            nohup $JAVA_HOME java $JVM_OPTS -jar $APP_HOME/$AppName --server.port=$SERVER_PORT > "$LOG_FILE" 2>&1 &
        else
            nohup $JAVA_HOME java $JVM_OPTS -jar $APP_HOME/$AppName > "$LOG_FILE" 2>&1 &
        fi
        # 检查启动状态
        status
    fi
}

# 停止函数
function stop() {
    echo "Stopping $AppName"
     while true; do
         PID=$(pid)
         if [ "$PID" = 0 ]; then
             # 如果进程已经停止，则输出提示信息
             echo "$AppName already stopped."
             break
         fi
         # 发送终止信号给进程
         echo "Sending termination signal to $AppName (pid:$PID)..."
         kill -TERM "$PID"

         # 等待进程退出
         echo "$AppName (pid:$PID) exiting..."
         while kill -0 "$PID" &> /dev/null; do
             sleep 1
         done
         echo "$AppName exited."
         break
     done
}

# 重启函数
function restart(){
    # 先停止项目，再启动项目
    stop
    sleep 2
    start
}

# 状态函数
function status(){
    PID=$(pid)
    PORT=$(port $PID)
    if [ $PID != 0 ];then
        # 如果进程在运行，则输出绿色提示信息
        echo -e "$AppName is \033[0;32m running... \033[0m  pid:$PID  port:$PORT"
        echo -e "running:$PID"
    else
        # 如果进程未运行，则输出红色提示信息
        echo -e "$AppName is \033[0;31m  not running... \033[0m"
    fi
}

# 主逻辑
case $1 in
    start)
    start;;
    stop)
    stop;;
    log)
    log; ;
    restart)
    restart;;
    status)
    status;;
    *)
    # 如果参数不匹配，则输出使用方法
    echo "使用方法: $0 {start|stop|restart|status|log}"
    exit 1;;
esac